package at.fhooe.SRWCProject.WiFiDirect;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.AlertDialog.Builder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.wifi.p2p.*;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.*;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import at.fhooe.SRWCProject.R;
import at.fhooe.SRWCProject.WiFiDirect.Socket.*;

public class ShareFileActivity extends Activity {

	// Stores names of traversed directories
	ArrayList<String> str = new ArrayList<String>();

	// Check if the first level of the directory structure is the one showing
	private Boolean firstLvl = true;

	private static final String TAG = "F_PATH";

	private Item[] fileList;
	private File path = new File(Environment.getExternalStorageDirectory() + "");
	private String chosenFile;
	private static final int DIALOG_LOAD_FILE = 1000;

	ListAdapter adapter;

	public static final int SOCKET_CONNECTED = 1;
	public static final int DATA_RECEIVED = 2;
	public static final int PORT = 6666;

	private TextView mTvData;
	private TextView mTvStatus;
	private ListView mLvDevices;
	private Button mBtnDiscover;

	private ArrayAdapter<WifiP2pDevice> mDevicesAdapter;
	private List<WifiP2pDevice> mDeviceList = new ArrayList<WifiP2pDevice>();

	private WifiP2pManager mWifiP2pManager;
	private WifiP2pManager.Channel mWifiP2pChannel;

	private IntentFilter mPeerFilter;
	private IntentFilter mConnectionFilter;
	private IntentFilter mP2pEnabledFilter;

	private ConnectionThread mConnection;

	private OutputStream myOutput = null;
	private InputStream myInput = null;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_share_file);
		// setContentView();

		mTvData = (TextView) findViewById(R.id.tvData);
		mTvStatus = (TextView) findViewById(R.id.tvStatus);
		mLvDevices = (ListView) findViewById(R.id.lvDevices);
		mBtnDiscover = (Button) findViewById(R.id.buttonDiscover);

		mDevicesAdapter = new ArrayAdapter<WifiP2pDevice>(this, android.R.layout.simple_list_item_1, mDeviceList);
		mLvDevices.setAdapter(mDevicesAdapter);

		initializeWifiP2p();

		mPeerFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);
		mConnectionFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
		mP2pEnabledFilter = new IntentFilter(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);

		mBtnDiscover.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() {
					@Override
					public void onSuccess() {

					}

					@Override
					public void onFailure(int i) {
						String error = "P2P failed. (" + i + ")";
						mTvStatus.setText(error);
					}
				});
			}
		});

		mLvDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> av, View v, int i, long l) {
				WifiP2pConfig p2pConfig = new WifiP2pConfig();
				p2pConfig.deviceAddress = mDeviceList.get(i).deviceAddress;
				Log.e("WE ARE nich gut", mDeviceList.get(i).deviceAddress.toString() + " "
						+ mDeviceList.get(i).deviceName.toString());
				mWifiP2pManager.connect(mWifiP2pChannel, p2pConfig, new WifiP2pManager.ActionListener() {
					@Override
					public void onSuccess() {

					}

					@Override
					public void onFailure(int i) {
						String error = "P2P failed. (" + i + ")";
						mTvStatus.setText(error);
					}
				});
				setTitle("Connecting...");
				setProgressBarIndeterminateVisibility(true);
			}
		});
	}

	@Override
	protected void onPause() {
		super.onPause();
		unregisterReceiver(mPeerDiscoveryReceiver);
		unregisterReceiver(mConnectionChangedReceiver);
		unregisterReceiver(mP2pEnabledReceiver);

		mWifiP2pManager.removeGroup(mWifiP2pChannel, null);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
//		unregisterReceiver(mPeerDiscoveryReceiver);
//		unregisterReceiver(mConnectionChangedReceiver);
//		unregisterReceiver(mP2pEnabledReceiver);

		mWifiP2pManager.removeGroup(mWifiP2pChannel, null);
	}

	@Override
	protected void onResume() {
		super.onResume();
		registerReceiver(mPeerDiscoveryReceiver, mPeerFilter);
		registerReceiver(mConnectionChangedReceiver, mConnectionFilter);
		registerReceiver(mP2pEnabledReceiver, mP2pEnabledFilter);
	}

	BroadcastReceiver mPeerDiscoveryReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			mWifiP2pManager.requestPeers(mWifiP2pChannel, new WifiP2pManager.PeerListListener() {
				@Override
				public void onPeersAvailable(WifiP2pDeviceList wifiP2pDeviceList) {
					mDeviceList.clear();
					mDeviceList.addAll(wifiP2pDeviceList.getDeviceList());
					mDevicesAdapter.notifyDataSetChanged();
				}
			});
		}
	};

	BroadcastReceiver mConnectionChangedReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);
			if (networkInfo.isConnected()) {
				mWifiP2pManager.requestConnectionInfo(mWifiP2pChannel, new WifiP2pManager.ConnectionInfoListener() {
					@Override
					public void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo) {
						if (wifiP2pInfo.groupFormed) {
							if (wifiP2pInfo.isGroupOwner) {
								mTvStatus.setText("Server");
								new AcceptThread(mHandler).start();
							} else {
								mTvStatus.setText("Client, connection to " + wifiP2pInfo.groupOwnerAddress);
								new ConnectThread(ShareFileActivity.this, wifiP2pInfo.groupOwnerAddress.toString(),
										mHandler).start();
							}
						}
					}
				});
			}
		}
	};

	private Handler mHandler = new Handler(new Handler.Callback() {
		@Override
		public boolean handleMessage(Message msg) {
			if (msg.what == SOCKET_CONNECTED) {
				setProgressBarIndeterminateVisibility(false);
				setTitle("Connected");
				mConnection = (ConnectionThread) msg.obj;
				mTvStatus.setText("Connected to " + mConnection.getInetAddress());

				// String hello = "Hello from "+mConnection.getInetAddress().getHostAddress();
				// mConnection.write(hello.getBytes());
				// /addMessage(mConnection.getInetAddress().getHostAddress(), hello);
			} else if (msg.what == DATA_RECEIVED) {
				// String data = (String) msg.obj;
				// addMessage(mConnection.getInetAddress().getHostAddress(), data);

				byte[] data = ((String) msg.obj).getBytes();
				try {
					if (!Arrays.equals(data, "EoF".getBytes()))
						saveFile(data);
					else {
						Toast.makeText(getApplicationContext(), "File copy Finished", Toast.LENGTH_LONG).show();

						if (myOutput != null) {
							myOutput.close();
						}
						if (myInput != null) {
							myInput.close();
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			return false;
		}

	});

	public void addMessage(String name, String message) {
		mTvData.append(name + ":" + message + "\n");
	}

	BroadcastReceiver mP2pEnabledReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, WifiP2pManager.WIFI_P2P_STATE_DISABLED);
			if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) {
				mBtnDiscover.setEnabled(true);
				mTvStatus.setText("P2P enabled");
			} else {
				mBtnDiscover.setEnabled(false);
				mTvStatus.setText("P2P disabled");
			}

		}
	};

	private void initializeWifiP2p() {
		mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
		mWifiP2pChannel = mWifiP2pManager.initialize(this, getMainLooper(), new WifiP2pManager.ChannelListener() {
			@Override
			public void onChannelDisconnected() {
				initializeWifiP2p();
			}
		});
	}

	public void saveFile(byte[] data) throws IOException {

		try {

			File f = new File("/mnt/sdcard/out.txt");
			if (!f.exists()) {
				myOutput = new FileOutputStream(f);
				// myInput = new FileInputStream(databasePath);
			}
			myOutput.write(data, 0, data.length);
			myOutput.flush();
		} catch (Exception e) {
			if (myOutput != null)
				myOutput.close();
			if (myInput != null)
				myInput.close();
		}

	}

	public void sendFile(String _path) {

		//String databasePath = "/mnt/sdcard/DB_DEBUG/rec.txt";
		String databasePath = _path;
		File f = new File(databasePath);
		OutputStream out = null;
		InputStream in = null;

		if (f.exists()) {
			try {

				in = new FileInputStream(databasePath);

				byte[] buffer = new byte[1024];
				int length, x = 0;
				while ((length = in.read(buffer)) > 0) {
					x++;
					Toast.makeText(getApplicationContext(), "Sending File part: " + x, Toast.LENGTH_SHORT).show();
					mConnection.write(buffer);
				}
				mConnection.write("EoF".getBytes());
				Toast.makeText(getApplicationContext(), "File Sent", Toast.LENGTH_LONG).show();

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				try {
					if (in != null) {
						in.close();
						in = null;
					}
				} catch (Exception e) {
				}
			}
		} else
			Toast.makeText(getApplicationContext(), "File doesn't exist", Toast.LENGTH_LONG).show();
	}

	public void onBtnClick(View v) {
		if (v.getId() == R.id.btnSendFile) {
			loadFileList();
			showDialog(DIALOG_LOAD_FILE);
			Log.d(TAG, path.getAbsolutePath());

		}
	}

	private void loadFileList() {
		try {
			path.mkdirs();
		} catch (SecurityException e) {
			Log.e(TAG, "unable to write on the sd card ");
		}

		// Checks whether path exists
		if (path.exists()) {
			FilenameFilter filter = new FilenameFilter() {
				@Override
				public boolean accept(File dir, String filename) {
					File sel = new File(dir, filename);
					// Filters based on whether the file is hidden or not
					return (sel.isFile() || sel.isDirectory()) && !sel.isHidden();

				}
			};

			String[] fList = path.list(filter);
			fileList = new Item[fList.length];
			for (int i = 0; i < fList.length; i++) {
				fileList[i] = new Item(fList[i], R.drawable.file_icon);

				// Convert into file path
				File sel = new File(path, fList[i]);

				// Set drawables
				if (sel.isDirectory()) {
					fileList[i].icon = R.drawable.download;
					Log.d("DIRECTORY", fileList[i].file);
				} else {
					Log.d("FILE", fileList[i].file);
				}
			}

			if (!firstLvl) {
				Item temp[] = new Item[fileList.length + 1];
				for (int i = 0; i < fileList.length; i++) {
					temp[i + 1] = fileList[i];
				}
				temp[0] = new Item("Up", R.drawable.directory_up);
				fileList = temp;
			}
		} else {
			Log.e(TAG, "path does not exist");
		}

		adapter = new ArrayAdapter<Item>(this, android.R.layout.select_dialog_item, android.R.id.text1, fileList) {
			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				// creates view
				View view = super.getView(position, convertView, parent);
				TextView textView = (TextView) view.findViewById(android.R.id.text1);

				// put the image on the text view
				textView.setCompoundDrawablesWithIntrinsicBounds(fileList[position].icon, 0, 0, 0);

				// add margin between image and text (support various screen
				// densities)
				int dp5 = (int) (5 * getResources().getDisplayMetrics().density + 0.5f);
				textView.setCompoundDrawablePadding(dp5);

				return view;
			}
		};

	}

	private class Item {
		public String file;
		public int icon;

		public Item(String file, Integer icon) {
			this.file = file;
			this.icon = icon;
		}

		@Override
		public String toString() {
			return file;
		}
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		Dialog dialog = null;
		AlertDialog.Builder builder = new Builder(this);

		if (fileList == null) {
			Log.e(TAG, "No files loaded");
			dialog = builder.create();
			return dialog;
		}

		switch (id) {
		case DIALOG_LOAD_FILE:
			builder.setTitle("Choose your file");
			builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialog, int which) {
					chosenFile = fileList[which].file;
					File sel = new File(path + "/" + chosenFile);
					if (sel.isDirectory()) {
						firstLvl = false;

						// Adds chosen directory to list
						str.add(chosenFile);
						fileList = null;
						path = new File(sel + "");

						loadFileList();

						removeDialog(DIALOG_LOAD_FILE);
						showDialog(DIALOG_LOAD_FILE);
						Log.d(TAG, path.getAbsolutePath());

					}

					// Checks if 'up' was clicked
					else if (chosenFile.equalsIgnoreCase("up") && !sel.exists()) {

						// present directory removed from list
						String s = str.remove(str.size() - 1);

						// path modified to exclude present directory
						path = new File(path.toString().substring(0, path.toString().lastIndexOf(s)));
						fileList = null;

						// if there are no more directories in the list, then
						// its the first level
						if (str.isEmpty()) {
							firstLvl = true;
						}
						loadFileList();

						removeDialog(DIALOG_LOAD_FILE);
						showDialog(DIALOG_LOAD_FILE);
						Log.d(TAG, path.getAbsolutePath());

					}
					// File picked
					else {
						sendFile(path.toString() + "/" + chosenFile.toString());
						// Toast.makeText(getApplicationContext(), path.toString(),
						// Toast.LENGTH_SHORT);
						// Log.wtf("DEBUG", "Path: "+path.toString());
					}

				}
			});
			break;
		}
		dialog = builder.show();
		return dialog;
	}

}
